from typing import Optional
from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from sqlalchemy.orm import Session
from itsdangerous import BadSignature, SignatureExpired

from app.models import get_db
from app.models.user import User
from app.utils.jwt_util import decode_access_token
from app.utils.redis_util import RedisUtil
from app.exception import AuthenticationError

# 指定令牌URL
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/auth/login", auto_error=False)

async def get_current_user(
    token: Optional[str] = Depends(oauth2_scheme),
    db: Session = Depends(get_db)
) -> User:
    """获取当前用户
    
    这是一个依赖项，用于获取请求中的当前认证用户
    
    Args:
        token: JWT令牌
        db: 数据库会话
    
    Returns:
        User: 当前用户
    
    Raises:
        AuthenticationError: 认证异常
    """
    if token is None:
        raise AuthenticationError("未提供认证令牌")
    
    try:
        # 解码令牌
        payload = decode_access_token(token)
        username: str = payload.get("sub")
        user_id: int = payload.get("user_id")
        
        if username is None or user_id is None:
            raise AuthenticationError("无效的认证令牌")
        
        # 检查令牌是否在Redis中（是否已登出）
        stored_token = RedisUtil.get(f"token:{user_id}")
        if not stored_token or stored_token != token:
            raise AuthenticationError("令牌已失效，请重新登录")
        
        # 查询用户
        user = db.query(User).filter(User.id == user_id).first()
        if user is None:
            raise AuthenticationError("用户不存在")
        
        # 检查用户状态
        if not user.is_active:
            raise AuthenticationError("用户已被禁用")
        
        return user
        
    except SignatureExpired:
        raise AuthenticationError("令牌已过期，请重新登录")
    except BadSignature:
        raise AuthenticationError("无效的认证令牌")

# 创建一个目录，确保中间件模块被正确识别
